# coding:utf-8
import logging


def log2console():
    """
    :function:简单的将日志打印到屏幕
    :return:
    """
    logging.debug('This is debug message')
    logging.info('This is info message')
    logging.warning('This is warning message')
    '''
        控制台输出：
            WARNING:root:This is warning message
    '''

def log2file():
    """
    :function:通过logging.basicConfig函数对日志的输出格式及方式做相关配置
    :return:
    """
    logging.basicConfig(level=logging.DEBUG,             # 设置日志级别，默认为logging.WARNING
                        format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                        datefmt='%a, %d %b %Y %H:%M:%S', # 指定时间格式，同time.strftime()
                        filename='log.log',              # 指定日志文件名
                        filemode='w')                    # 和file函数意义相同，指定日志文件的打开模式，'w'或'a'
    #format:指定输出的格式和内容
        # %(asctime)s: 日志的时间
        # %(filename)s: 当前执行程序名
        # %(lineno)d: 日志的当前行号
        # %(levelname)s: 日志级别名称
        # %(message)s: 日志信息
        # %(levelno)s: 日志级别的数值
        # %(pathname)s: 当前执行程序的路径，其实就是sys.argv[0]
        # %(funcName)s: 日志的当前函数
        # %(thread)d: 线程ID
        # %(threadName)s: 线程名称
        # %(process)d: 进程ID

    logging.debug('This is debug message')
    logging.info('This is info message')
    logging.warning('This is warning message')

    '''
        控制台没有显示
        当前目录生成文件log.log，其内容为：
            Fri, 02 Jun 2017 10:16:49 logger.py[line:11] DEBUG This is debug message
            Fri, 02 Jun 2017 10:16:49 logger.py[line:12] INFO This is info message
            Fri, 02 Jun 2017 10:16:49 logger.py[line:13] WARNING This is warning message
    '''


def log2consoleAndFile():
    """
    :function:将日志同时输出到文件和屏幕
    :return:
    """
    logging.basicConfig(level=logging.DEBUG,
                        format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                        datefmt='%a, %d %b %Y %H:%M:%S',
                        filename='log.log',
                        filemode='w')

    # 定义一个StreamHandler，将INFO级别或更高的日志信息打印到标准错误，并将其添加到当前的日志处理对象
    console = logging.StreamHandler()
    formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
    console.setFormatter(formatter)
    console.setLevel(logging.INFO)
    logging.getLogger('').addHandler(console)

    logging.debug('This is debug message')
    logging.info('This is info message')
    logging.warning('This is warning message')

    '''
        控制台输出：
            root        : INFO     This is info message
            root        : WARNING  This is warning message
        文件中输出：
            Fri, 02 Jun 2017 10:35:53 logger.py[line:72] DEBUG This is debug message
            Fri, 02 Jun 2017 10:35:53 logger.py[line:73] INFO This is info message
            Fri, 02 Jun 2017 10:35:53 logger.py[line:74] WARNING This is warning message
    '''


def logRotateByFileSize():
    """
    :function:日志滚动,按照文件大小
    :return:
    """
    from logging.handlers import RotatingFileHandler
    # 定义一个RotatingFileHandler，最多备份5个日志文件，每个日志文件最大10M
    RHandler = RotatingFileHandler('log.log', maxBytes=10 * 1024 * 1024, backupCount=5)
    formatter = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')
    RHandler.setFormatter(formatter)
    RHandler.setLevel(logging.DEBUG)
    logging.getLogger('').addHandler(RHandler)

    logging.debug('This is debug message')
    logging.info('This is info message')
    logging.warning('This is warning message')

    '''
        通过addHandler添加日志处理对象，logging的handle方式如下：
            logging.StreamHandler: 日志输出到流，可以是sys.stderr、sys.stdout或者文件
            logging.FileHandler: 日志输出到文件
            # 由于StreamHandler和FileHandler是常用的日志处理方式，所以直接包含在logging模块中，
            # 而其他方式则包含在logging.handlers模块中

            # 日志滚动方式，实际使用时用RotatingFileHandler和TimedRotatingFileHandler
            logging.handlers.BaseRotatingHandler
            logging.handlers.RotatingFileHandler
            logging.handlers.TimedRotatingFileHandler
            logging.handlers.SocketHandler: 远程输出日志到TCP/IP sockets
            logging.handlers.DatagramHandler:  远程输出日志到UDP sockets
            logging.handlers.SMTPHandler:  远程输出日志到邮件地址
            logging.handlers.SysLogHandler: 日志输出到syslog
            logging.handlers.NTEventLogHandler: 远程输出日志到Windows NT/2000/XP的事件日志
            logging.handlers.MemoryHandler: 日志输出到内存中的制定buffer
            logging.handlers.HTTPHandler: 通过"GET"或"POST"远程输出到HTTP服务器
    '''


def logRotateByTime():
    """
    :function:日志滚动,按照时间
    :return:
    """
    import time
    import re
    from logging.handlers import TimedRotatingFileHandler

    # 日志打印格式
    log_fmt = '%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s'
    formatter = logging.Formatter(log_fmt)
    # 创建TimedRotatingFileHandler对象

    log_file_handler = TimedRotatingFileHandler(filename="log", when="S", interval=30, backupCount=2)
    log_file_handler.suffix = "%Y-%m-%d_%H-%M-%S.log"
    log_file_handler.extMatch = re.compile(r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}.log$")
    log_file_handler.setFormatter(formatter)
    logging.basicConfig(level=logging.INFO)
    log = logging.getLogger()
    log.addHandler(log_file_handler)
    # 循环打印日志
    log_content = "test log"
    count = 0
    while count < 60:
        log.error(log_content)
        time.sleep(5)  # 每隔5秒输出一次log，每隔30秒生成一个文件(when="S", interval=30)，最多保留2个文件(backupCount=2)
        count = count + 1
    log.removeHandler(log_file_handler)

    """
        TimedRotatingFileHandler的参数含义
            filename：日志文件名的prefix；
            when：是一个字符串，用于描述滚动周期的基本单位，字符串的值及意义如下：
                “S”: Seconds
                “M”: Minutes
                “H”: Hours
                “D”: Days
                “W”: Week day (0=Monday)
                “midnight”: Roll over at midnight
            interval: 滚动周期，单位有when指定，比如：when=’D’,interval=1，表示每天产生一个日志文件；
            backupCount: 表示日志文件的保留个数

        suffix是指日志文件名的后缀,suffix中通常带有格式化的时间字符串
            filename和suffix由“.”连接构成文件名
            例如：filename="runtime"， suffix="%Y-%m-%d.log",生成的文件名为runtime.2015-07-06.log
        extMatch是一个编译好的正则表达式，用于匹配日志文件名的后缀
            它必须和suffix是匹配的，如果suffix和extMatch匹配不上的话，过期的日志是不会被删除的
            比如，suffix="%Y-%m-%d.log", extMatch的只应该是re.compile(r"^\d{4}-\d{2}-\d{2}.log$")
            默认情况下，在TimedRotatingFileHandler对象初始化时，suffxi和extMatch会根据when的值进行初始化：
                'S':suffix="%Y-%m-%d_%H-%M-%S", extMatch=r"\^d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}"
                'M':suffix="%Y-%m-%d_%H-%M",    extMatch=r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}"
                'H':suffix="%Y-%m-%d_%H",       extMatch=r"^\d{4}-\d{2}-\d{2}_\d{2}"
                'D':suffxi="%Y-%m-%d",          extMatch=r"^\d{4}-\d{2}-\d{2}"
                'MIDNIGHT':"%Y-%m-%d",          extMatch=r"^\d{4}-\d{2}-\d{2}"
                'W':"%Y-%m-%d",                 extMatch=r"^\d{4}-\d{2}-\d{2}"
            如果对日志文件名没有特殊要求的话，可以不用设置suffix和extMatch，如果需要，一定要让它们匹配上。
    """

def logByConfig():
    """
    :function:通过logging.config模块配置日志
    :param log.conf:配置文件
    :return:
    """
    import logging.config

    logging.config.fileConfig("log.conf")
    logger = logging.getLogger("example01")

    logger.debug('This is debug message')
    logger.info('This is info message')
    logger.warning('This is warning message')


if __name__ == '__main__':
    # log2console()
    # log2file()
    # log2consoleAndFile()
    # logRotateByFileSize()
    logRotateByTime()
    # logByConfig()